home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / aspisrc.zip / BUFFER.C < prev    next >
C/C++ Source or Header  |  1992-01-26  |  32KB  |  1,362 lines

  1. /* Buffer management for tar.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Buffer management for tar.
  22.  *
  23.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  24.  *
  25.  * @(#) buffer.c 1.28 11/6/87 - gnu
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <errno.h>
  30. #include <sys/types.h>        /* For non-Berkeley systems */
  31. #include <sys/stat.h>
  32. #include <signal.h>
  33.  
  34. #ifndef MSDOS
  35. #include <sys/ioctl.h>
  36. #if !defined(USG) || defined(HAVE_MTIO)
  37. #include <sys/mtio.h>
  38. #endif
  39. #endif
  40.  
  41. #ifdef    MSDOS
  42. # include <fcntl.h>
  43. #include <process.h>
  44. #else
  45. # ifdef XENIX
  46. #  include <sys/inode.h>
  47. # endif
  48. # include <sys/file.h>
  49. #endif
  50.  
  51. extern int errno;
  52.  
  53. #include "tar.h"
  54. #include "port.h"
  55. #include "rmt.h"
  56. #include "regex.h"
  57.  
  58. /* Either stdout or stderr:  The thing we write messages (standard msgs, not
  59.    errors) to.  Stdout unless we're writing a pipe, in which case stderr */
  60. FILE *msg_file = stdout;
  61.  
  62. #define    STDIN    0        /* Standard input  file descriptor */
  63. #define    STDOUT    1        /* Standard output file descriptor */
  64.  
  65. #define    PREAD    0        /* Read  file descriptor from pipe() */
  66. #define    PWRITE    1        /* Write file descriptor from pipe() */
  67.  
  68. #ifdef __STDC__
  69. extern void    *malloc();
  70. extern void    *valloc();
  71. #else
  72. extern char    *malloc();
  73. extern char    *valloc();
  74. #endif
  75. extern time_t time();
  76.  
  77. extern char    *index(), *strcat();
  78. extern char    *strcpy();
  79.  
  80. /*
  81.  * V7 doesn't have a #define for this.
  82.  */
  83. #ifndef O_RDONLY
  84. #define    O_RDONLY    0
  85. #endif
  86. #ifndef O_RDWR
  87. #define O_RDWR        2
  88. #endif
  89. #ifndef O_CREAT
  90. #define O_CREAT        0
  91. #endif
  92. #ifndef O_BINARY
  93. #define O_BINARY    0
  94. #endif
  95.  
  96. #define    MAGIC_STAT    105    /* Magic status returned by child, if
  97.                    it can't exec.  We hope compress/sh
  98.                    never return this status! */
  99.  
  100. void writeerror();
  101. void readerror();
  102.  
  103. void ck_pipe();
  104. void ck_close();
  105.  
  106. extern void finish_header();
  107. extern void to_oct();
  108.  
  109. #ifndef __MSDOS__
  110. /* Obnoxious test to see if dimwit is trying to dump the archive */
  111. dev_t ar_dev;
  112. ino_t ar_ino;
  113. #endif
  114.  
  115. /*
  116.  * The record pointed to by save_rec should not be overlaid
  117.  * when reading in a new tape block.  Copy it to record_save_area first, and
  118.  * change the pointer in *save_rec to point to record_save_area.
  119.  * Saved_recno records the record number at the time of the save.
  120.  * This is used by annofile() to print the record number of a file's
  121.  * header record.
  122.  */
  123. static union record **save_rec;
  124.  union record record_save_area;
  125. static long        saved_recno;
  126.  
  127. /*
  128.  * PID of child program, if f_compress or remote archive access.
  129.  */
  130. static int    childpid = 0;
  131.  
  132. /*
  133.  * Record number of the start of this block of records
  134.  */
  135. long    baserec;
  136.  
  137. /*
  138.  * Error recovery stuff
  139.  */
  140. static int    r_error_count;
  141.  
  142. /*
  143.  * Have we hit EOF yet?
  144.  */
  145. static int    eof;
  146.  
  147. /* JF we're reading, but we just read the last record and its time to update */
  148. extern time_to_start_writing;
  149. int file_to_switch_to= -1;    /* If remote update, close archive, and use
  150.                    this descriptor to write to */
  151.  
  152. static int volno = 1;        /* JF which volume of a multi-volume tape
  153.                    we're on */
  154.  
  155. char *save_name = 0;        /* Name of the file we are currently writing */
  156. long save_totsize;        /* total size of file we are writing.  Only
  157.                    valid if save_name is non_zero */
  158. long save_sizeleft;        /* Where we are in the file we are writing.
  159.                    Only valid if save_name is non-zero */
  160.  
  161. int write_archive_to_stdout;
  162.  
  163. /* Used by fl_read and fl_write to store the real info about saved names */
  164. static char real_s_name[NAMSIZ];
  165. static long real_s_totsize;
  166. static long real_s_sizeleft;
  167.  
  168. /* Reset the EOF flag (if set), and re-set ar_record, etc */
  169.  
  170. void
  171. reset_eof()
  172. {
  173.     if(eof) {
  174.         eof=0;
  175.         ar_record=ar_block;
  176.         ar_last=ar_block+blocking;
  177.         ar_reading=0;
  178.     }
  179. }
  180.  
  181. /*
  182.  * Return the location of the next available input or output record.
  183.  * Return NULL for EOF.  Once we have returned NULL, we just keep returning
  184.  * it, to avoid accidentally going on to the next file on the "tape".
  185.  */
  186. union record *
  187. findrec()
  188. {
  189.     if (ar_record == ar_last) {
  190.         if (eof)
  191.             return (union record *)NULL;    /* EOF */
  192.         flush_archive();
  193.         if (ar_record == ar_last) {
  194.             eof++;
  195.             return (union record *)NULL;    /* EOF */
  196.         }
  197.     }
  198.     return ar_record;
  199. }
  200.  
  201.  
  202. /*
  203.  * Indicate that we have used all records up thru the argument.
  204.  * (should the arg have an off-by-1? XXX FIXME)
  205.  */
  206. void
  207. userec(rec)
  208.     union record *rec;
  209. {
  210.     while(rec >= ar_record)
  211.         ar_record++;
  212.     /*
  213.      * Do NOT flush the archive here.  If we do, the same
  214.      * argument to userec() could mean the next record (if the
  215.      * input block is exactly one record long), which is not what
  216.      * is intended.
  217.      */
  218.     if (ar_record > ar_last)
  219.         abort();
  220. }
  221.  
  222.  
  223. /*
  224.  * Return a pointer to the end of the current records buffer.
  225.  * All the space between findrec() and endofrecs() is available
  226.  * for filling with data, or taking data from.
  227.  */
  228. union record *
  229. endofrecs()
  230. {
  231.     return ar_last;
  232. }
  233.  
  234.  
  235. /*
  236.  * Duplicate a file descriptor into a certain slot.
  237.  * Equivalent to BSD "dup2" with error reporting.
  238.  */
  239. void
  240. dupto(from, to, msg)
  241.     int from, to;
  242.     char *msg;
  243. {
  244.     int err;
  245.  
  246.     if (from != to) {
  247.         err=close(to);
  248.         if(err<0 && errno!=EBADF) {
  249.             msg_perror("Cannot close descriptor %d",to);
  250.             exit(EX_SYSTEM);
  251.         }
  252.         err = dup(from);
  253.         if (err != to) {
  254.             msg_perror("cannot dup %s",msg);
  255.             exit(EX_SYSTEM);
  256.         }
  257.         ck_close(from);
  258.     }
  259. }
  260.  
  261. #ifdef MSDOS
  262. void
  263. child_open()
  264. {
  265.     fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar);
  266.     exit(EX_ARGSBAD);
  267. }
  268. #else
  269. void
  270. child_open()
  271. {
  272.     int pipe[2];
  273.     int err = 0;
  274.  
  275.     int kidpipe[2];
  276.     int kidchildpid;
  277.  
  278. #define READ    0
  279. #define WRITE    1
  280.  
  281.     ck_pipe(pipe);
  282.  
  283.     childpid=fork();
  284.     if(childpid<0) {
  285.         msg_perror("cannot fork");
  286.         exit(EX_SYSTEM);
  287.     }
  288.     if(childpid>0) {
  289.         /* We're the parent.  Clean up and be happy */
  290.         /* This, at least, is easy */
  291.  
  292.         if(ar_reading) {
  293.             f_reblock++;
  294.             archive=pipe[READ];
  295.             ck_close(pipe[WRITE]);
  296.         } else {
  297.             archive = pipe[WRITE];
  298.             ck_close(pipe[READ]);
  299.         }
  300.         return;
  301.     }
  302.  
  303.     /* We're the kid */
  304.     if(ar_reading) {
  305.         dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout");
  306.         ck_close(pipe[READ]);
  307.     } else {
  308.         dupto(pipe[READ],STDIN,"(child) pipe to stdin");
  309.         ck_close(pipe[WRITE]);
  310.     }
  311.  
  312.     /* We need a child tar only if
  313.        1: we're reading/writing stdin/out (to force reblocking)
  314.        2: the file is to be accessed by rmt (compress doesn't know how)
  315.        3: the file is not a plain file */
  316. #ifdef NO_REMOTE
  317.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file))
  318. #else
  319.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file))
  320. #endif
  321.     {
  322.         /* We don't need a child tar.  Open the archive */
  323.         if(ar_reading) {
  324.             archive=open(ar_file, O_RDONLY|O_BINARY, 0666);
  325.             if(archive<0) {
  326.                 msg_perror("can't open archive %s",ar_file);
  327.                 exit(EX_BADARCH);
  328.             }
  329.             dupto(archive,STDIN,"archive to stdin");
  330.             /* close(archive); */
  331.         } else {
  332.             archive=creat(ar_file,0666);
  333.             if(archive<0) {
  334.                 msg_perror("can't open archive %s",ar_file);
  335.                 exit(EX_BADARCH);
  336.             }
  337.             dupto(archive,STDOUT,"archive to stdout");
  338.             /* close(archive); */
  339.         }
  340.     } else {
  341.         /* We need a child tar */
  342.         ck_pipe(kidpipe);
  343.  
  344.         kidchildpid=fork();
  345.         if(kidchildpid<0) {
  346.             msg_perror("child can't fork");
  347.             exit(EX_SYSTEM);
  348.         }
  349.  
  350.         if(kidchildpid>0) {
  351.             /* About to exec compress:  set up the files */
  352.             if(ar_reading) {
  353.                 dupto(